#include "hplczkysfindpacket.h"
#include "hplczkyspacketformat.h"
#include "hplczkyspfcid.h"
#include "common/convert.h"
#include "common/misc.h"
#include "common/str.h"
#include <QDebug>
#include "debug.h"

namespace hplc
{
namespace zkys
{

HplcZkysFindPacket::HplcZkysFindPacket(QObject *parent)
    : BaseFindPacket (parent)
{

}

HplcZkysFindPacket::~HplcZkysFindPacket()
{

}

QList<ProtocolPacket> HplcZkysFindPacket::find(const QByteArray &data)
{
    m_rxBuffer.append(data);

    QList<ProtocolPacket>   packets;
    while (m_rxBuffer.size() > 0)
    {
        quint8 _data = m_rxBuffer.at(0);
        m_rxBuffer.remove(0, 1); //剔除

        switch(m_state)
        {
        case 0: // 检查帧头
            if (_data == ZKYS_PROTOCOL_HEAD_TAIL) //帧头
            {
                m_state = 1;
                m_rxBufferBeforeUnescape.clear();
                m_rxBufferBeforeUnescape.append(_data);
            }
            break;
        case 1: // 接收数据
            if (_data == ZKYS_PROTOCOL_HEAD_TAIL) // 防止连续出现2个帧头
            {
                m_statistics->m_current.m_receivedErrorPackets++;
                qWarning("\r\n Format error \r\n");
                emit errorPacket(ZKYS_REPLY_PEC_FORMAT);

                continue;
            }

            m_rxBufferBeforeUnescape.append(_data);
            m_state = 2;
            break;
        case 2:
            m_rxBufferBeforeUnescape.append(_data);

            if (_data == ZKYS_PROTOCOL_HEAD_TAIL) //帧尾对
            {
                m_state = 0;

                //逆向转义
                if (!unescape())
                {
                    m_statistics->m_current.m_receivedErrorPackets++;
                    qWarning("\r\n ReverseEscape error \r\n");
                    emit errorPacket(ZKYS_REPLY_PEC_FORMAT);
                    continue;
                }

#if (CRC16_ENABLE)
                // CRC校验
                if (!str::checkCRC16((uint8_t*)(m_rxPacket.data()), m_rxPacket.size()))
                {
                    m_statistics->m_current.m_receivedErrorPackets++;
                    emit errorPacket(ZKYS_REPLY_PEC_CRC);
                    qWarning("\r\n CheckCRC16 error \r\n");
                    continue;
                }
#endif
                m_statistics->m_current.m_receivedCorrectBytes += m_rxPacket.size();
                m_statistics->m_current.m_receivedCorrectPackets++;

                // 一包普通的包
                ProtocolPacket packet;
                packet.timestamp = Misc::getTimeStamp();
                packet.buffer = m_rxPacket;
                packets << packet;
                m_rxPacket.clear();
//                qDebug() << "packet.buffer : " << packet.buffer;
            }

            break;
        default:
            m_state = 0;
            break;
        } // switch
    } // while
    return packets;
}

bool HplcZkysFindPacket::unescape()
{
    m_rxPacket.clear();
//    m_rxPacket.append(m_rxBufferBeforeUnescape.at(0)); //保存帧头
    for (int i = 1; i < m_rxBufferBeforeUnescape.size() - 1; i++)
    {
        quint8 data = m_rxBufferBeforeUnescape.at(i);
        if (data == ZKYS_PROTOCOL_ESCAPE_OUT1)
        {
            quint8 dataNext = m_rxBufferBeforeUnescape.at(i+1);
            if (dataNext == ZKYS_PROTOCOL_ESCAPE_OUT2)
            {
                m_rxPacket.append(ZKYS_PROTOCOL_ESCAPE);
                i++;
            }
            else if (dataNext == ZKYS_PROTOCOL_ESCAPE2_OUT2)
            {
                m_rxPacket.append(ZKYS_PROTOCOL_ESCAPE2);
                i++;
            }
            else // 0xEA后不是0xFD/0xED，表示帧错误
            {
                return false;
            }
        }
        else
        {
            m_rxPacket.append(data);
        }
    }
//    m_rxPacket.append(m_rxBufferBeforeUnescape.at(m_rxBufferBeforeUnescape.size() - 1)); //保存帧尾

    return true;
}

} // zkys
} // hplc
